package com.ktgj.hotel.controller;

import cn.hutool.core.codec.Base64Decoder;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.ktgj.common.core.constant.BusinessTypeConstants;
import com.ktgj.common.core.constant.CustomerConstants;
import com.ktgj.common.core.utils.xml.XElement;
import com.ktgj.hotel.domain.HotelOrder;
import com.ktgj.hotel.domain.HotelOrderException;
import com.ktgj.hotel.domain.HotelOrderPaydetail;
import com.ktgj.hotel.domain.HotelOrderRoom;
import com.ktgj.hotel.domain.rooms.CreateOrderResult;
import com.ktgj.hotel.domain.vo.BillPayment;
import com.ktgj.hotel.domain.vo.PaymentCallbackVo;
import com.ktgj.hotel.domain.vo.PhoneSoundCallback;
import com.ktgj.hotel.mapper.HotelOrderExceptionMapper;
import com.ktgj.hotel.mapper.HotelOrderMapper;
import com.ktgj.hotel.mapper.HotelOrderPaydetailMapper;
import com.ktgj.hotel.mapper.HotelOrderRoomMapper;
import com.ktgj.hotel.service.IHotelOrderService;
import com.ktgj.hotel.service.IHotelService;
import com.ktgj.pay.api.RemotePayService;
import com.ktgj.pay.api.domain.AlipayConfigApi;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.*;

@ControllerAdvice
@RestController
@RequestMapping("/callback")
public class CallbackController {

    @Autowired
    private IHotelOrderService hotelOrderService;
    @Autowired
    private RemotePayService payService;
    @Autowired
    private IHotelService hotelService;
    @Autowired
    private HotelOrderMapper hotelOrderMapper;
    @Autowired
    private HotelOrderPaydetailMapper hotelOrderPaydetailMapper;
    @Autowired
    private HotelOrderRoomMapper hotelOrderRoomMapper;
    @Autowired
    private HotelOrderExceptionMapper hotelOrderExceptionMapper;

    /**
     * 酒店微信支付回调
     * */
    @RequestMapping("/hotelWechatPayCallback")
    public void vipHallWechatPayCallback(HttpServletRequest request, @RequestBody Map<String, String> resultMap){
        boolean result = payService.isPaySuccessful(resultMap);
        String returnCode = resultMap.put("return_code", resultMap.get("return_code"));
        String resultCode = resultMap.put("result_code", resultMap.get("result_code"));
        String outTradeNo = resultMap.put("out_trade_no", resultMap.get("out_trade_no"));
        String transaction_id = resultMap.put("transaction_id", resultMap.get("transaction_id"));
        if (result) {

            HotelOrder num = null;

            if (returnCode.equals("SUCCESS") && resultCode.equals("SUCCESS")) {//交易成功
                if (outTradeNo != null) {//商户订单号
                    HotelOrder hotelOrder = new HotelOrder();
                    hotelOrder.setOrderstatusid(1l);
                    hotelOrder.setPlusmoneystatus(CustomerConstants.payd.getValue());
                    hotelOrder.setOrderNum(outTradeNo);
                    hotelOrder.setSerial(transaction_id);
                    int i = hotelOrderMapper.updateStatus(hotelOrder);
                    if (i <= 0){
                        System.out.println("微信支付回调修改订单信息失败");
                    }

                    num = hotelOrderMapper.selectHotelOrderByOrderNum(outTradeNo);

                    HotelOrderPaydetail hotelOrderPaydetail = new HotelOrderPaydetail();
                    hotelOrderPaydetail.setOrderid(num.getOrderid());
                    hotelOrderPaydetail.setPaytype(BusinessTypeConstants.Wechat.getValue());
                    int j = hotelOrderPaydetailMapper.updatePayType(hotelOrderPaydetail);
                    if (j <= 0){
                        System.out.println("微信支付回调修改订单支付信息失败");
                    }

                    CreateOrderResult order = null;

                    try {
                        String backCardNum = hotelOrderMapper.selectHotelOrderByOrderNum(outTradeNo).getBackCardNum();
                        order = hotelService.bankCreateOrder(Long.valueOf(outTradeNo), backCardNum);
                    } catch (Exception e){
                        System.out.println(e.getMessage());
                    }

                    if (order.Code.equals("0")){
                        System.out.println("艺龙下单成功");
                    }
                    else {
                        System.out.println("艺龙下单失败" + order.Code);
                    }
                }
            }
            else {
                if (outTradeNo != null) {//商户订单号

                    HotelOrderException hotelOrderException = new HotelOrderException();

                    List<HotelOrderRoom> hotelOrderRoomList = hotelOrderRoomMapper.selectHotelOrderRoomByOrderNum(outTradeNo);
                    if (hotelOrderRoomList != null && hotelOrderRoomList.size() > 0){
                        String person = null;
                        for (int i = 0; i < hotelOrderRoomList.size(); i++) {
                            if (i == 0){
                                person = hotelOrderRoomList.get(i).getGuestname();
                            }
                            else {
                                person = person + "|" + hotelOrderRoomList.get(i).getGuestname();
                            }
                        }
                        hotelOrderException.setPerson(person);
                    }
                    hotelOrderException.setPersonPhone(num.getPhone());
                    hotelOrderException.setHotelName(num.getHotelname());
                    hotelOrderException.setReserveTime(num.getCreateTime());
                    hotelOrderException.setExceptionInfo("支付失败");
                    hotelOrderException.setSourceWay("App");
                    hotelOrderException.setStatus("processed");
                    hotelOrderException.setOrderId(num.getOrderid().toString());
                    hotelOrderException.setOrderType("reserve");
                    hotelOrderException.setEmployeeId(10l);
                    hotelOrderExceptionMapper.insertHotelOrderException(hotelOrderException);

                    HotelOrder hotelOrder = new HotelOrder();
                    hotelOrder.setOrderstatusid(400l);
                    hotelOrder.setPlusmoneystatus(CustomerConstants.failPay.getValue());
                    hotelOrder.setOrderNum(outTradeNo);
                    int i = hotelOrderMapper.updateStatus(hotelOrder);
                    if (i <= 0){
                        System.out.println("微信支付回调修改订单信息失败");
                    }
                }
            }
        }
    }

    /**
     * 酒店语音支付回调
     * */
    @RequestMapping("/hotelVoicePayCallback")
    public void hotelVoicePayCallback(HttpServletResponse response, HttpServletRequest request){
        PhoneSoundCallback phoneSoundCallback = new PhoneSoundCallback();
        try
        {
            request.setCharacterEncoding("UTF-8");
//            response_xml=String(Base64Decode(UrlDecode(request.getParameter(response_text),UTF-8)),UTF-8)
            String response_xml = Base64Decoder.decodeStr(request.getParameter("response_text"));
            XElement root = XElement.loadXml(response_xml);
            phoneSoundCallback.setAccountType(root.element("AccountType").getValue());
            phoneSoundCallback.setAcqSsn(root.element("AcqSsn").getValue());
            phoneSoundCallback.setAmount(root.element("Amount").getValue());
            phoneSoundCallback.setAccountNo(root.element("AccountNo").getValue());
            phoneSoundCallback.setAsynAddress(root.element("AsynAddress").getValue());
            phoneSoundCallback.setCurrency(root.element("Currency").getValue());
            phoneSoundCallback.setDescription(root.element("Description").getValue());
            phoneSoundCallback.setMAC(root.element("MAC").getValue());
            phoneSoundCallback.setMerchantNo(root.element("MerchantNo").getValue());
            phoneSoundCallback.setMerchantOrderNo(root.element("MerchantOrderNo").getValue());
            phoneSoundCallback.setMethod(root.element("Method").getValue());
            phoneSoundCallback.setOrderNo(root.element("OrderNo").getValue());
            phoneSoundCallback.setOrderState(root.element("OrderState").getValue());
            phoneSoundCallback.setOrderType(root.element("OrderType").getValue());
            phoneSoundCallback.setProcCode(root.element("ProcCode").getValue());
            phoneSoundCallback.setProcessCode(root.element("ProcessCode").getValue());
            phoneSoundCallback.setRemark(root.element("Remark").getValue());
            phoneSoundCallback.setRespCode(root.element("RespCode").getValue());
            phoneSoundCallback.setSettleDate(root.element("SettleDate").getValue());
            phoneSoundCallback.setTerminalNo(root.element("TerminalNo").getValue());
            phoneSoundCallback.setTsNo(root.element("TsNo").getValue());
            phoneSoundCallback.setUpsNo(root.element("UpsNo").getValue());
            phoneSoundCallback.setUserPayedTime(root.element("UserPayedTime").getValue());
            phoneSoundCallback.setVersion(root.element("Version").getValue());
        } catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }

        HotelOrder num = null;

        if (phoneSoundCallback.getRespCode().equals("0000")){//交易成功
            if (phoneSoundCallback.getMerchantOrderNo() != null){
                HotelOrder hotelOrder = new HotelOrder();
                hotelOrder.setOrderstatusid(1l);
                hotelOrder.setPlusmoneystatus(CustomerConstants.payd.getValue());
                hotelOrder.setOrderNum(phoneSoundCallback.getMerchantOrderNo());
                hotelOrder.setSerial(phoneSoundCallback.getOrderNo());
                int i = hotelOrderMapper.updateStatus(hotelOrder);
                if (i <= 0){
                    System.out.println("语音支付回调修改订单信息失败");
                }

                num = hotelOrderMapper.selectHotelOrderByOrderNum(phoneSoundCallback.getMerchantOrderNo());

                HotelOrderPaydetail hotelOrderPaydetail = new HotelOrderPaydetail();
                hotelOrderPaydetail.setOrderid(num.getOrderid());
                hotelOrderPaydetail.setPaytype(BusinessTypeConstants.PhoneSoundPay.getValue());
                int payType = hotelOrderPaydetailMapper.updatePayType(hotelOrderPaydetail);
                if (payType <= 0){
                    System.out.println("语音支付回调修改订单支付信息失败");
                }

                CreateOrderResult order = null;

                try {
                    order = hotelService.bankCreateOrder(Long.valueOf(phoneSoundCallback.getMerchantOrderNo()), phoneSoundCallback.getAccountNo());
                } catch (Exception e){
                    System.out.println(e.getMessage());
                }

                if (order.Code.equals("0")){
                    System.out.println("艺龙下单成功");
                }
                else {
                    System.out.println("艺龙下单失败" + order.Code);
                }
            }
        }
        else {
            if (phoneSoundCallback.getMerchantOrderNo() != null){

                HotelOrderException hotelOrderException = new HotelOrderException();

                List<HotelOrderRoom> hotelOrderRoomList = hotelOrderRoomMapper.selectHotelOrderRoomByOrderNum(phoneSoundCallback.getMerchantOrderNo());
                if (hotelOrderRoomList != null && hotelOrderRoomList.size() > 0){
                    String person = null;
                    for (int n = 0; n < hotelOrderRoomList.size(); n++) {
                        if (n == 0){
                            person = hotelOrderRoomList.get(n).getGuestname();
                        }
                        else {
                            person = person + "|" + hotelOrderRoomList.get(n).getGuestname();
                        }
                    }
                    hotelOrderException.setPerson(person);
                }
                hotelOrderException.setPersonPhone(num.getPhone());
                hotelOrderException.setHotelName(num.getHotelname());
                hotelOrderException.setReserveTime(num.getCreateTime());
                hotelOrderException.setExceptionInfo("支付失败");
                hotelOrderException.setSourceWay("App");
                hotelOrderException.setStatus("processed");
                hotelOrderException.setOrderId(num.getOrderid().toString());
                hotelOrderException.setOrderType("reserve");
                hotelOrderException.setEmployeeId(10l);
                hotelOrderExceptionMapper.insertHotelOrderException(hotelOrderException);

                HotelOrder hotelOrder = new HotelOrder();
                hotelOrder.setOrderstatusid(400l);
                hotelOrder.setPlusmoneystatus(CustomerConstants.failPay.getValue());
                hotelOrder.setOrderNum(phoneSoundCallback.getMerchantOrderNo());
                hotelOrder.setSerial("");
                int i = hotelOrderMapper.updateStatus(hotelOrder);
                if (i <= 0){
                    System.out.println("语音支付回调修改订单信息失败");
                }
            }
        }
    }

    /**
     * 银联二维码回调
     * */
    @PostMapping("/hotelUnionQRCodePayCallback")
    public void hotelUnionQRCodePayCallback(HttpServletResponse response, HttpServletRequest request){
        PaymentCallbackVo paymentCallbackVo = new PaymentCallbackVo();
        String parameter = request.getParameter("billPayment");
        BillPayment parseObject = JSONObject.parseObject(parameter, BillPayment.class);
        paymentCallbackVo.setBillPayment(parseObject);
        paymentCallbackVo.setMid(request.getParameter("mid"));//商户号
        paymentCallbackVo.setTid(request.getParameter("tid"));//终端号
        paymentCallbackVo.setInstMid(request.getParameter("instMid"));//业务类型
        paymentCallbackVo.setBillNo(request.getParameter("billNo"));//账单号
        paymentCallbackVo.setBillQRCode(request.getParameter("billQRCode"));//账单二维码
        paymentCallbackVo.setBillStatus(request.getParameter("billStatus"));//账单状态
        paymentCallbackVo.setBillDesc(request.getParameter("billDesc"));//账单描述
        paymentCallbackVo.setMemberId(request.getParameter("memberId"));//会员号
        paymentCallbackVo.setCounterNo(request.getParameter("counterNo"));//桌号、柜台号、房间号
        paymentCallbackVo.setMerName(request.getParameter("merName"));//商户名称
        paymentCallbackVo.setMemo(request.getParameter("memo"));//付款附言
        paymentCallbackVo.setNotifyId(request.getParameter("notifyId"));//支付通知ID
        paymentCallbackVo.setSecureStatus(request.getParameter("secureStatus"));//担保状态
        paymentCallbackVo.setCompleteAmount(request.getParameter("completeAmount"));//担保完成金额（分）
        paymentCallbackVo.setBillDate(request.getParameter("billDate"));//订单时间，格式yyyy-MM-dd
        paymentCallbackVo.setCreateTime(request.getParameter("createTime"));//账单创建时间，格式yyyy-MM-dd HH:mm:ss
        paymentCallbackVo.setSign(request.getParameter("sign"));//签名
        paymentCallbackVo.setExtraBuyerInfo(request.getParameter("extraBuyerInfo"));//用户额外信息

        HotelOrder num = null;

        if (paymentCallbackVo.getBillStatus().equals("PAID")) {

            num = hotelOrderMapper.selectHotelOrderByOrderNum(paymentCallbackVo.getBillNo().substring(4));

            HotelOrderPaydetail hotelOrderPaydetail = new HotelOrderPaydetail();
            hotelOrderPaydetail.setOrderid(num.getOrderid());
            hotelOrderPaydetail.setPaytype(BusinessTypeConstants.UnionPayQRCode.getValue());
            int i = hotelOrderPaydetailMapper.updatePayType(hotelOrderPaydetail);
            if (i <= 0){
                System.out.println("二维码支付回调修改订单支付信息失败");
            }

            try {
                String backCardNum = hotelOrderMapper.selectHotelOrderByOrderNum(paymentCallbackVo.getBillNo().substring(4)).getBackCardNum();
                if (!num.getPlusmoneystatus().equals(CustomerConstants.payd.getValue()) && num.getOrderstatusid() != 400) {
                    HotelOrder hotelOrder = new HotelOrder();
                    hotelOrder.setPlusmoneystatus(CustomerConstants.payd.getValue());
                    hotelOrder.setOrderNum(paymentCallbackVo.getBillNo().substring(4));
                    hotelOrder.setSerial(paymentCallbackVo.getBillNo());
                    int updateStatus = hotelOrderMapper.updateStatus(hotelOrder);
                    if (updateStatus <= 0){
                        System.out.println("二维码支付回调修改订单信息失败");
                    }

                    CreateOrderResult order = hotelService.bankCreateOrder(Long.valueOf(paymentCallbackVo.getBillNo().substring(4)), backCardNum);
                    if (order.Code.equals("0")){
                        System.out.println("艺龙下单成功");
                        hotelOrder.setOrderstatusid(1l);
                        int status = hotelOrderMapper.updateStatus(hotelOrder);
                        if (status <= 0){
                            System.out.println("二维码支付回调修改订单信息失败");
                        }
                    }
                    else {
                        System.out.println("艺龙下单失败" + order.Code);
                        hotelOrder.setOrderstatusid(400l);
                        int status = hotelOrderMapper.updateStatus(hotelOrder);
                        if (status <= 0){
                            System.out.println("二维码支付回调修改订单信息失败");
                        }
                    }
                }
            } catch (Exception e){
                System.out.println(e.getMessage());
            }
        } else {

            HotelOrderException hotelOrderException = new HotelOrderException();

            List<HotelOrderRoom> hotelOrderRoomList = hotelOrderRoomMapper.selectHotelOrderRoomByOrderNum(paymentCallbackVo.getBillNo().substring(4));
            if (hotelOrderRoomList != null && hotelOrderRoomList.size() > 0){
                String person = null;
                for (int n = 0; n < hotelOrderRoomList.size(); n++) {
                    if (n == 0){
                        person = hotelOrderRoomList.get(n).getGuestname();
                    }
                    else {
                        person = person + "|" + hotelOrderRoomList.get(n).getGuestname();
                    }
                }
                hotelOrderException.setPerson(person);
            }
            hotelOrderException.setPersonPhone(num.getPhone());
            hotelOrderException.setHotelName(num.getHotelname());
            hotelOrderException.setReserveTime(num.getCreateTime());
            hotelOrderException.setExceptionInfo("支付失败");
            hotelOrderException.setSourceWay("App");
            hotelOrderException.setStatus("processed");
            hotelOrderException.setOrderId(num.getOrderid().toString());
            hotelOrderException.setOrderType("reserve");
            hotelOrderException.setEmployeeId(10l);
            hotelOrderExceptionMapper.insertHotelOrderException(hotelOrderException);

            HotelOrder hotelOrder = new HotelOrder();
            hotelOrder.setOrderNum(paymentCallbackVo.getBillNo());
            hotelOrder.setPlusmoneystatus(CustomerConstants.failPay.getValue()); //支付失败
            hotelOrder.setOrderstatusid(400l);
            hotelOrder.setSerial("");
            int i = hotelOrderMapper.updateStatus(hotelOrder);
            if (i <= 0){
                System.out.println("二维码支付回调修改订单信息失败");
            }
        }

        PrintWriter printWriter;
        response.setCharacterEncoding("UTF-8");
        try {
            printWriter = response.getWriter();
            printWriter.write("SUCCESS");
            printWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 支付成功后回调测试(支付宝回调必须是post方式的回调)
     * */
    @PostMapping("/hotelAliPayCallback")
    public void hotelAliPayCallback(HttpServletRequest request) throws UnsupportedEncodingException {
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        //log.info("支付宝验签:{}", jsonString4JavaPOJO);

        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        String out_trade_no = request.getParameter("out_trade_no");            // 商户订单号
        String trade_no = request.getParameter("trade_no");            // 流水号
        String tradeStatus = request.getParameter("trade_status");
        String total_amount = request.getParameter("total_amount");  //订单金额

        //签名验证(对支付宝返回的数据验证，确定是支付宝返回的)
        boolean signVerified = false;
        try {
            //3.1调用SDK验证签名
            signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfigApi.ALIPAY_PUBLIC_KEY, AlipayConfigApi.CHARSET, AlipayConfigApi.SIGN_TYPE);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        //4.对验签进行处理
        if (signVerified) {    //验签通过
            if (tradeStatus.equals("TRADE_SUCCESS")) {    //只处理支付成功的订单: 修改交易表状态,支付成功
                HotelOrder hotelOrder = new HotelOrder();
                hotelOrder.setOrderstatusid(1l);
                hotelOrder.setPlusmoneystatus(CustomerConstants.payd.getValue());
                hotelOrder.setOrderNum(out_trade_no);
                hotelOrder.setSerial(trade_no);
                int i = hotelOrderMapper.updateStatus(hotelOrder);
                if (i <= 0){
                    System.out.println("支付宝支付回调修改订单信息失败");
                }

                HotelOrder num = hotelOrderMapper.selectHotelOrderByOrderNum(out_trade_no);

                HotelOrderPaydetail hotelOrderPaydetail = new HotelOrderPaydetail();
                hotelOrderPaydetail.setOrderid(num.getOrderid());
                hotelOrderPaydetail.setPaytype(BusinessTypeConstants.Alipay.getValue());
                int updatePayType = hotelOrderPaydetailMapper.updatePayType(hotelOrderPaydetail);
                if (updatePayType <= 0){
                    System.out.println("支付宝支付回调修改订单支付信息失败");
                }

                CreateOrderResult order = null;

                try {
                    String backCardNum = hotelOrderMapper.selectHotelOrderByOrderNum(out_trade_no).getBackCardNum();
//                order = hotelService.bankCreateOrder(Long.valueOf(paymentCallbackVo.getBillNo()), backCardNum);
                } catch (Exception e){
                    System.out.println(e.getMessage());
                }

                if (order.Code.equals("0")){
                    System.out.println("艺龙下单成功");
                }
                else {
                    System.out.println("艺龙下单失败" + order.Code);
                }
            }
            else {
                HotelOrder hotelOrder = new HotelOrder();
                hotelOrder.setOrderNum(out_trade_no);
                hotelOrder.setPlusmoneystatus(CustomerConstants.failPay.getValue()); //支付失败
                hotelOrder.setQrCard(out_trade_no);
                hotelOrder.setSerial("");
                int i = hotelOrderMapper.updateStatus(hotelOrder);
                if (i <= 0){
                    System.out.println("支付宝支付回调修改订单信息失败");
                }
            }
        }
    }

    /**
     * 支付成功后回调测试(云闪付（银联）回调必须是post方式的回调)
     * */
    @PostMapping("/hotelUnionPayCallback")
    public void hotelUnionPayCallback(HttpServletRequest request){
//        LogUtil.writeLog("BackRcvResponse接收后台通知开始");
//        String encoding = request.getParameter(SDKConstants.param_encoding);
        // 获取银联通知服务器发送的后台通知参数
        Map<String, String> reqParam = getAllRequestParam(request);
        boolean isSuccess = false;
    }

    public static Map<String, String> getAllRequestParam(final HttpServletRequest request) {
        Map<String, String> res = new HashMap<String, String>();
        Enumeration<?> temp = request.getParameterNames();
        if (null != temp) {
            while (temp.hasMoreElements()) {
                String en = (String) temp.nextElement();
                String value = request.getParameter(en);
                res.put(en, value);
                //在报文上送时，如果字段的值为空，则不上送<下面的处理为在获取所有参数数据时，判断若值为空，则删除这个字段>
                //System.out.println("ServletUtil类247行  temp数据的键=="+en+"     值==="+value);
                if (null == res.get(en) || "".equals(res.get(en))) {
                    res.remove(en);
                }
            }
        }
        return res;
    }

    /**
     * 银联二维码退款回调
     * */
    @PostMapping("/retreatUnionPayQRCallback")
    public void retreatUnionPayQRCallback(){}
}
